import pandas as pd
import requests
import time
import csv
import re

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36'
}


def fetch_comments(video_id, max_pages=10000):
    comments = []
    last_count = 0
    next_offset = 0  # 初始偏移量

    for page in range(1, max_pages + 1):
        url = f'https://api.bilibili.com/x/v2/reply/main?type=1&oid={video_id}&mode=3&next={next_offset}'
        try:
            response = requests.get(url, headers=headers, timeout=10)
            if response.status_code == 200:
                data = response.json()
                print(f"正在抓取第 {page} 页评论")

                if not data.get('data') or not data['data'].get('replies'):
                    print("评论已抓取完毕，停止翻页")
                    break

                for comment in data['data']['replies']:
                    comment_info = {
                        '评论内容': comment['content']['message'],
                        '性别': comment['member']['sex'],
                        '点赞数量': comment['like'],
                        '回复时间': time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(comment['ctime']))
                    }
                    comments.append(comment_info)

                next_offset = data['data'].get('cursor', {}).get('next', 0)
                if next_offset == 0 or last_count == len(comments):
                    print("已到最后一页，停止翻页")
                    break

                last_count = len(comments)
            else:
                print(f"请求失败，状态码: {response.status_code}")
                break
        except requests.RequestException as e:
            print(f"请求出错: {e}")
            break

        time.sleep(0.2)

    return comments


def save_comments_to_csv(comments, video_bvname):
    with open(f'.\\数据\\{video_bvname}.csv', mode='w', encoding='utf-8-sig', newline='') as file:
        writer = csv.DictWriter(file, fieldnames=['性别', '评论内容', '点赞数量', '回复时间'])
        writer.writeheader()
        for comment in comments:
            writer.writerow(comment)


def normalize_comment(comment):
    """标准化评论内容，移除标点符号，仅保留文字"""
    return re.sub(r'[^\w\u4e00-\u9fa5]', '', comment).lower()


def remove_bracketed_content(comment):
    """去除评论中的 [内容] 部分"""
    return re.sub(r'\[.*?\]', '', comment).strip()


def process_comments(input_file, output_file, filtered_output_file):
    df = pd.read_csv(input_file, encoding='utf-8-sig')

    # 性别转换
    gender_mapping = {'男': 1, '女': 2, '保密': 0}
    df['性别'] = df['性别'].map(gender_mapping)

    # 转换回复时间为datetime格式
    df['回复时间'] = pd.to_datetime(df['回复时间'])

    # 清洗评论内容
    df['评论内容'] = df['评论内容'].apply(remove_bracketed_content)
    df = df[df['评论内容'].str.contains(r'[a-zA-Z\u4e00-\u9fa5]', na=False)]

    # 按点赞总数分组并清洗数据
    cleaned_df = df.groupby('评论内容').agg({
        '性别': 'first',
        '点赞数量': 'sum',
        '回复时间': 'first'
    }).reset_index()

    # 保存清洗数据
    cleaned_df.to_csv(output_file, index=False, encoding='utf-8-sig')

    print("请选择筛选方式：")
    print("1. 筛选点赞量前 8% 的数据")
    print("2. 筛选出点赞量大于等于 20 的评论")
    choice = input("请输入筛选方式（1 或 2）：")

    if choice == "1":
        # 筛选点赞量前 10% 的数据
        threshold = int(len(cleaned_df) * 0.1)
        filtered_df = cleaned_df.nlargest(threshold, '点赞数量')
    elif choice == "2":
        # 筛选出点赞量大于等于 20 的评论
        filtered_df = cleaned_df[cleaned_df['点赞数量'] >= 20]
    else:
        print("选择无效，强制退出")
        return

    # 保存筛选数据
    filtered_df.to_csv(filtered_output_file, index=False, encoding='utf-8-sig')


video_oid = input("请输入视频的oid: ")
video_name = input("请输入视频的名字: ")

print(f'视频名字: {video_name}, video_oid: {video_oid}')
comments = fetch_comments(video_oid)
csv_file = f'.\\数据\\{video_name}.csv'
save_comments_to_csv(comments, video_name)

output_csv = f'.\\数据\\清洗数据_{video_name}.csv'
filtered_output_csv = f'.\\数据\\筛选数据_{video_name}.csv'
process_comments(csv_file, output_csv, filtered_output_csv)

print(f"评论抓取和合并完成，清洗结果保存至 {output_csv}")
print(f"筛选结果保存至 {filtered_output_csv}")
